package de.gameduell.framework.locale {
	import de.gameduell.framework.debug.Debug;
	
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.SimpleButton;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;	

	public class Locale extends EventDispatcher {

		private static var instance:Locale;
		
		public static const SEPARATOR:String = ".";
		
		public static const AUTO_SIZE:String  = "autoSize";
		public static const HTML:String	      = "html";
		public static const VARIABLES:String  = "variables";
		public static const CONDITION:String  = "condition";	
		public static const DEFAULT_AUTOSIZE:String = TextFieldAutoSize.NONE;
		
		private var map:Array;
		private var window:DisplayObjectContainer;	
		private var xmlList:Array;
		private var localeData:LocaleData = LocaleData.getInstance();
		
		public static function getInstance():Locale{
			if(instance == null){
				instance = new Locale();
			}
			return instance;
		}
			
		public function Locale() {
			map  	= new Array();
			xmlList = new Array();
		}
		
		public function init(aWindow:DisplayObjectContainer, aLang:XML, aGeneral:XML):void {		
			addXML(aLang);
			addXML(aGeneral);
					
			window = aWindow;
			window.addEventListener(Event.ADDED, childAdded);
			localizeChildren(window);	
		}
		
		public function addXML(aXML:XML):void{
			xmlList.push(aXML);
			var nodes:XMLList = aXML.children();
			for(var i:* in nodes){
				var node:XML = XML(nodes[i]);
				map[node.name()] = node;
			}
		}
		
		private function childAdded(event:Event):void {
			try{
				var child:DisplayObject = event.target as DisplayObject;
				if(child != null){
					localizeDisplayObject(child);
				}
			}catch(e:Error){
				Debug.trace("Locale::childAdded " + e,Debug.ERROR);
			}
		}

		public function localize(aLocalizable:Localizable):void {
			var children:Array = aLocalizable.localizableChildren;
			localizeChildren(aLocalizable.sprite, aLocalizable.id + SEPARATOR);	
			writeLocalizableText(aLocalizable);
			for(var i:int = 0;i < children.length;i++) {
				localize(children[i]);
			}
		}	

		public function writeLocalizableText(aLocalizable:Localizable,aUpdateVariables:Boolean = true):void {
			try {			
				var id:String = aLocalizable.id;
				var node:XML = map[id] as XML;	

				if(node != null) {	
					if(containsDynamicFeatures(node)) {
						new DynamicContent(aLocalizable,getNodes(id),aUpdateVariables);
					}else {					
						var autoSize:String = getAutoSize(node);
						var isHtml:Boolean  = containsHtml(node);
						var text:String     = isHtml ? LocaleTools.convertBrackets(node.text()) : node.text();
						aLocalizable.setText(text, isHtml, autoSize);
					}
				}
			}catch(e:Error) {
				Debug.trace("Locale::writeLocalizableText " + e, Debug.ERROR);
			}
		}

		public function loadString(id:String, replaceVariables:Boolean = false):String{
			if (replaceVariables){
				return LocaleTools.replaceVariables(loadOriginalString(id), localeData);
			} else {
				return loadOriginalString(id);
			}
		}
		
		private function loadOriginalString(id:String):String{
			try{
				var node:XML = map[id] as XML;
				if(containsHtml(node)){
					return LocaleTools.convertBrackets(node.text());
				}
				return node.text();
			}catch(e:Error){
//				Debug.trace("Locale::loadString: -> node not found: " + id, Debug.WARNING);
			}
			return "";
		}
		
		public function localizeChildren(object:DisplayObjectContainer,prefix:String="") : void {
			for(var i:int=0; i< object.numChildren;i++){	
				localizeDisplayObject(object.getChildAt(i),prefix);
			}
		}
		
		public function localizeDisplayObject(child:DisplayObject,prefix:String = ""):void{
			switch(true){
				case child is DisplayObjectContainer:
					if(prefix == ""){
						localizeChildren(child as DisplayObjectContainer, prefix);
					}else{
						localizeChildren(child as DisplayObjectContainer, prefix + child.name + SEPARATOR);
					}
					break;
				case child is TextField:
					localizeTextField(child as TextField, prefix);
					break;	
				case child is SimpleButton:
					localizeSimpleButton(child as SimpleButton, prefix)	;
			}
		}
		
		private function localizeSimpleButton(button:SimpleButton, prefix:String):void {
			var buttonStates:Array = new Array(button.upState,button.downState,button.overState);
			for(var i:* in buttonStates){
				localizeDisplayObject(buttonStates[i],prefix);
			}
		}

		private function localizeTextField(textField:TextField,prefix:String = ""):void{	
			textField.mouseWheelEnabled = false;
			var id:String = prefix+textField.name;
			localize(new LocalizableTextField(textField,id));
		}
		
		private function containsDynamicFeatures(node:XML):Boolean{
			return containsVariables(node) || containsCondition(node);
		}
		
		public function containsVariables(node:XML):Boolean{
			return node.attribute(VARIABLES) == "true";
		}
		
		public function containsCondition(node:XML):Boolean{
			var condition:XMLList = node.attribute(CONDITION);
			return condition.length() > 0;
		}
		
		public function containsHtml(node:XML):Boolean{
			return node.attribute(HTML) == "true";
		}
			
		public function getNodes(id:String):Array{
			var matches:Array = new Array();
			for(var i:* in xmlList){
				var nodes:XMLList = xmlList[i].children();
				for(var j:* in nodes){
					var node:XML = XML(nodes[j]);
					if(id == node.name()){
						matches.push(node);
					}
				}
			}
			return matches;
		}
	
		public function getAutoSize(node:XML):String{
			var autoSizeExists:Boolean = node.attribute(AUTO_SIZE).length() > 0;
			return autoSizeExists ? node.attribute(AUTO_SIZE) : DEFAULT_AUTOSIZE;	
		}

		public function getAttributeValue(node:XML, attributeKey:String):String {
			var attributeExists:Boolean = node.attribute(attributeKey).length() > 0;
			return attributeExists ? node.attribute(attributeKey) : null;	
		}

	}
}
